require "fileutils"
class Image < ActiveRecord::Base
  belongs_to :group
  has_and_belongs_to_many :tags
  belongs_to :user

  # this creates a 'tags' collection, thru a has_and_belongs_to_many
  # relationship that utilizes the join table 'tags_images'.


  acts_as_taggable
  validates_presence_of :filename #confusingly named this way
                                  #filename => path to the file in our system
  validates_presence_of :user_id
  validates_length_of :name, :in => 1..255,:too_short => "is a bit too short. At least 1 character please.",
      :too_long => "should be under %d characters"
  after_create :upload_image
  before_destroy :delete_images

  PRESET_SIZES = {"small" => {:suffix => "s", :dimension => 100}, #these sizes are in pixels
                "medium" => {:suffix => "m", :dimension => 250},  #used for thumbnailing
                "large" => {:suffix => "l", :dimension => 500},
                "huge" => {:suffix => "h", :dimension => 1000}
                }
  PICTURE_FOLDER_PATH = File::join(RAILS_ROOT, "public","pictures")

  def upload_image
    if self.filename == nil
      raise ActiveRecordError, "no filename found for uploading"
    else
      #filename to save : id_in_db.ext (e.g. 1.jpg, 2.png, 3.tiff)
      filename_with_id = self.id.to_s + File.extname(self.filename.original_filename)

      FileUtils.copy_file(self.filename.path,"#{RAILS_ROOT}/public/pictures/#{filename_with_id}")
#      File.open("#{RAILS_ROOT}/public/pictures/#{filename_with_id}", "wb") do |f|
#        f.write(self.filename.read) #File object was serialized in the DB
#      end

      puts "fienamewith id" + YAML.dump(filename_with_id)
      update_attribute(:filename, filename_with_id) #update with new filename

      create_thumbnails(File::join(PICTURE_FOLDER_PATH , self.filename))
    end
  end

  def delete_images
    if self.filename.class==String
      File.delete("#{RAILS_ROOT}/public/pictures/#{self.filename}") if File.exist?("#{RAILS_ROOT}/public/pictures/#{self.filename }")
    end

    if self.small_file.class==String
      File.delete("#{RAILS_ROOT}/public/pictures/#{self.small_file}") if File.exist?("#{RAILS_ROOT}/public/pictures/#{self.small_file}")
    end

    if self.medium_file.class==String
      File.delete("#{RAILS_ROOT}/public/pictures/#{self.medium_file}") if File.exist?("#{RAILS_ROOT}/public/pictures/#{self.medium_file}")
    end

    if self.large_file.class==String
      File.delete("#{RAILS_ROOT}/public/pictures/#{self.large_file}") if File.exist?("#{RAILS_ROOT}/public/pictures/#{self.large_file}")
    end

    if self.huge_file.class==String
      File.delete("#{RAILS_ROOT}/public/pictures/#{self.huge_file}") if File.exist?("#{RAILS_ROOT}/public/pictures/#{self.huge_file}")
    end
  end

  def create_thumbnails(file)
    require 'rubygems'
    require 'RMagick'

    raise RuntimeError, "Cannot find file to create thumbnail" if not File.exists?(file)
    begin

      img = Magick::Image.read(file).first #only first frame
                                           #BEWARE: multilayer GIFs?

      PRESET_SIZES.each do |size_name, size|
        #big enough for scaling?
        next if size[:dimension] > img.rows && size[:dimension] > img.columns
        puts "File is #{file}"
        puts "img is " +img.inspect

        #figure out scale ratio
        if img.rows > img.columns
          scale_ratio = size[:dimension].to_f / img.rows.to_f
        else
          scale_ratio = size[:dimension].to_f / img.columns.to_f
        end

        puts "Figuring out the ratio " + scale_ratio.to_s
        puts "Start doing the scaling part"
        #actually do the scaling

        #filename depends on PRESET_SIZES suffix
        new_img_filename = self.id.to_s + '_' + size[:suffix] + File.extname(self.name)
        puts "new_img_filename: " + new_img_filename
        new_img_path = File::join(PICTURE_FOLDER_PATH, new_img_filename)
        #saving this in the DB?
        puts "new_img_path:" + new_img_path
        new_img = img.thumbnail(scale_ratio)
        new_img.write(new_img_path)
        puts "new_img: " + new_img.inspect
        update_attribute((size_name+'_file').intern, new_img_filename)
      end
    rescue Exception => e
      puts e.to_s + " :Img> " + img.inspect
      #TODO: propagate this error to controller for display in the view
      #TODO: mark these records in the DB so not to display them
    end
  end

  protected :create_thumbnails

end